package main

import (
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"gitcode.net/togolife/nfttoken/common"
	"gitcode.net/togolife/nfttoken/event"
	"gitcode.net/togolife/nfttoken/handler"
)

var mainLog common.NftLog

func init() {
	err := common.LoadConfig("./conf/config.conf")
	if err != nil {
		panic("load config failed!")
	}
	mainLog = common.GetNftLog("main")
}

func dealChainLog(chain string, chainInfo common.ChainInfo, quit chan int) {
	exitFlag := make(chan int)
	chainLog := make(chan event.LogEmit)
	flag := true
	if err := event.SubscribeEvent(chain, chainInfo, exitFlag, chainLog); err != nil {
		mainLog.LogE("Subscribe to watch chain [%v], wss [%v] failed!", chain, chainInfo.NodeWssPath)
		flag = false
	}
	for {
		select {
		case _ = <-quit:
			if flag {
				exitFlag <- 0
			}
			return
		case log := <-chainLog:
			switch log.Type {
			case -1:
				mainLog.LogE("Got subscribe failed!")
				if err := event.SubscribeEvent(chain, chainInfo, exitFlag, chainLog); err != nil {
					mainLog.LogE("Resubscribe to watch chain [%v], wss [%v] failed!", chain, chainInfo.NodeWssPath)
					flag = false
				}
			case -2:
				mainLog.LogW("Got deal log failed!")
			default:
				handler.NotifyChainLog(log)
			}
		}
	}
}

func dealSignalExit(quit []chan int, proSignal chan os.Signal) {
	exit := false
	for !exit {
		select {
		case s := <-proSignal:
			if s == syscall.SIGINT || s == syscall.SIGTERM {
				for _, v := range quit {
					v <- 0
				}
				exit = true
			}
		}
	}
	mainLog.LogI("Caught exit signal, process exited!")
	os.Exit(0)
}

func main() {
	quit := []chan int{}
	for k, v := range common.GlobalConf.SupportChains {
		if len(v.NodeWssPath) > 0 && len(v.WatchAddress) > 0 {
			q := make(chan int)
			quit = append(quit, q)
			go dealChainLog(k, v, q)
		}
	}
	proSignal := make(chan os.Signal)
	signal.Notify(proSignal, syscall.SIGINT, syscall.SIGTERM)
	go dealSignalExit(quit, proSignal)
	http.HandleFunc("/trade/upload", handler.UploadToIpfsIf)
	http.HandleFunc("/trade/mint", handler.MintIf)
	http.HandleFunc("/trade/transfer", handler.TransferIf)
	http.HandleFunc("/trade/burn", handler.BurnIf)
	http.HandleFunc("/trade/approval", handler.ApprovalIf)
	http.HandleFunc("/trade/approvalForAll", handler.ApprovalForAllIf)
	http.HandleFunc("/account/create", handler.CreateAccountIf)
	http.HandleFunc("/query/account", handler.QueryAccountIf)
	http.HandleFunc("/query/trade", handler.QueryTradeIf)
	http.HandleFunc("/query/totalSupply", handler.QueryTotalIf)
	http.HandleFunc("/query/token", handler.QueryTokenIf)
	http.HandleFunc("/query/balance", handler.QueryBalanceIf)
	http.HandleFunc("/query/approved", handler.QueryApprovedIf)
	http.HandleFunc("/query/approvedForAll", handler.QueryApprovedForAllIf)
	err := http.ListenAndServe(common.GlobalConf.ServerAddr, nil)
	if err != nil {
		mainLog.LogE("ListenAndServe: ", err)
	}
	return
}
